/*
 * sys.c
 *
 *  Created on: 2018年5月6日
 *      Author: 0yfj0
 */

#include "sys_utils.h"
#include "nrf_error.h"
#include "app_error.h"
#include "nrf_nvmc.h"
#include "nrf_nvic.h"
#include "ble_flash.h"
#include "sys.h"

/*----------------------------------------------------------------------------*/
sys_t sys;

/*----------------------------------------------------------------------------*/
void sys_error_handle(void)
{
	NVIC_SystemReset();
}
uint16_t sys_var_write(int var, uint32_t off, void *buff, uint16_t len)
{
	return 0;
}
uint16_t sys_var_read(int var, uint32_t off, void *buff, uint16_t len)
{
	return 0;
}

#define SYS_CONF_SZ		( 128 )
int sys_conf_read(uint16_t off, void *buff, uint16_t len)
{
	int retval = -1;
	uint16_t size;
	uint8_t *buf;

	if (off + len > SYS_CONF_SZ || !buff)
		return -1;

	size = SYS_CONF_SZ + 2;
	buf = (uint8_t*) sys_malloc(size);
	if (buf == NULL)
		return -1;

	if (sys_flash_read(SYS_FLASH_CONF, 0, (uint32_t*) buf, size) == size)
	{
		if (crc16_ccit_calc_s(buf, size) == 0)
		{
			memcpy(buff, &buf[off], len);
			retval = 0;
		}
	}
	sys_free(buf);
	return retval;
}
int sys_conf_write(uint16_t off, void *buff, uint16_t len)
{
	int retval = -1;
	uint16_t size;
	uint16_t crc16;
	uint8_t *buf;

	if (off + len > SYS_CONF_SZ || !buff)
		return -1;

	size = SYS_CONF_SZ + 2;
	buf = (uint8_t*) sys_malloc(size);
	if (buf == NULL)
		return -1;
	if (sys_flash_read(SYS_FLASH_CONF, 0, (uint32_t*) buf, size) != size
			|| crc16_ccit_calc_s(buf, size) != 0)
		memset(buf, 0xFF, size);
	memcpy(&buf[off], buff, len);
	crc16 = crc16_ccit_calc_s(buf, SYS_CONF_SZ);
	buf[SYS_CONF_SZ + 0] = (uint8_t) (crc16 >> 8);
	buf[SYS_CONF_SZ + 1] = (uint8_t) (crc16 >> 0);
	if (sys_flash_write(SYS_FLASH_CONF, 0, (uint32_t*) buf, size) == size)
		retval = 0;
	sys_free(buf);
	return retval;
}

/*----------------------------------------------------------------------------*/
int sys_flash_erase(int page)
{
	uint32_t address;

	if (page < SYS_FLASH_START || page > SYS_FLASH_END)
		return -1;

	address = page * SYS_FLASH_SIZE;
	__disable_irq();
	nrf_nvmc_page_erase(address);
	__enable_irq();
	return 0;
}
int sys_flash_write(int sector, int off, void *buf, uint16_t len)
{
	uint32_t address;
	uint32_t words;
	uint32_t bytes;
	uint32_t value;

	if (sector < SYS_FLASH_START || sector > SYS_FLASH_END)
		return -1;
	if (off < 0 || off + len > SYS_FLASH_SIZE || !buf)
		return -1;

	if (off == 0 && sys_flash_erase(sector) != 0)
		return -1;
	words = len >> 2;
	bytes = len & 0x3;
	__disable_irq();
	if (words)
	{
		address = sector * SYS_FLASH_SIZE + off;
		nrf_nvmc_write_words(address, (uint32_t*) buf, words);
	}
	if (bytes)
	{
		address = sector * SYS_FLASH_SIZE + off + (words << 2);
		memset(&value, 0xFF, sizeof(value));
		memcpy(&value, (uint8_t*) buf + (words << 2), bytes);
		nrf_nvmc_write_word(address, value);
	}
	__enable_irq();
	return len;
}
int sys_flash_read(int sector, int off, void *buf, uint16_t len)
{
	uint32_t address;

	if (sector < SYS_FLASH_START || sector > SYS_FLASH_END)
		return -1;
	if (off < 0 || off + len > SYS_FLASH_SIZE || !buf)
		return -1;

	address = sector * SYS_FLASH_SIZE + off;
	memcpy(buf, (void*) address, len);
	return len;
}
